﻿using Microsoft.RestrictedUsage.CSharp.Syntax;
using Microsoft.RestrictedUsage.CSharp.Semantics;
using Microsoft.RestrictedUsage.CSharp.Core;
using Microsoft.RestrictedUsage.CSharp.Compiler.IDE;
using Microsoft.RestrictedUsage.CSharp.Extensions;
using System.Collections.Generic;
using System;
using System.Linq;
using Microsoft.RestrictedUsage.CSharp.Compiler;
using Microsoft.VisualStudio.Text;
using System.Diagnostics;
using Microsoft.VisualStudio.CSharp.Services.Language.Refactoring;


namespace Marias.Extensions.Csharp
{
    internal class CodeAnalyzer
    {
        private IDECompilerHost _CompilerHost;
        private ITextBuffer buffer;
        private IDECompiler _compiler;
        private bool _IsValid = false;

        internal CodeAnalyzer(string p_FileName)
        {
            _CompilerHost = new IDECompilerHost();
            foreach (IDECompiler i_comp in _CompilerHost.Compilers)
            {
                if (i_comp.SourceFiles.Keys.Contains(new FileName(p_FileName)))
                {
                    _compiler = i_comp;
                    _IsValid = true;
                }
            }

        }

        internal NodeType IsParameter(string p_filename, SpanDescriptor p_desc)
        {

            ParseTree i_tree;
            try
            {
                i_tree = _compiler.SourceFiles[new FileName(p_filename)].GetParseTree();
            } catch
            {
                return NodeType.Unknown;
            }


            Position i_pos = new Position(p_desc.LineNumber, p_desc.ColNumber);
            ParseTreeNode i_ptn = i_tree.FindLeafNode(i_pos);
            if (i_ptn as IdentifierNode != null)
            {
                string name = (i_ptn as IdentifierNode).Name.Text;
                if (i_ptn.ParseTree.GetType() == typeof(MethodBodyParseTree))
                {

                    MethodBaseNode i_meth = ParseTreeExtensions.GetContainingNode<MethodBaseNode>(i_ptn);
                    if (i_meth == null) return NodeType.Unknown;
                    //Compilation i_comp = _CompilerHost.Compilers[0].GetCompilation();
                    //CSharpMember i_func = i_comp.GetMemberForMethodDeclaration(i_meth);

                    var p = from m in i_meth.FormalParameterList
                            where m.AsParameter().Identifier.Name.Text == name
                            select m;
                    if (p.Count() > 0)
                        return NodeType.Parameter;
                                        
                    List<VariableDeclaratorNode> i_list = new List<VariableDeclaratorNode>();
                    GetAllDeclarationNode(i_ptn.ParseTree.RootNode, i_list);

                    var s = from l in i_list
                            where l.Identifier.Name.Text == name && ParseTreeMatch.GetVarDeclKind(l) == ParseTreeMatch.VarDeclKind.vdkLocalVar
                            select l;
                    if (s.Count() > 0)
                        return NodeType.LocalVariable;
                                        
                }
            }

            if (i_ptn.Parent.IsParameter())
                return NodeType.Parameter;

            return NodeType.Unknown;
        }

        internal void GetAllDeclarationNode(ParseTreeNode p_node, List<VariableDeclaratorNode> p_list)
        {
            if (p_node.AsVariableDeclaration() != null)
                p_list.Add(p_node.AsVariableDeclaration());
            foreach (ParseTreeNode n in p_node.Children)
                GetAllDeclarationNode(n, p_list);
        }
    }
}
